package com.wise.service.portal.content.code;

import com.wise.framework.consts.Consts;
import com.wise.framework.exception.LogicException;
import com.wise.model.content.CheckCodeResult;
import com.wise.model.content.utils.GetCodeFromCache;
import com.wise.model.content.utils.SetCode2Cache;
import com.wise.summer.v1.portal.content.verificationcode.CheckVerificationCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.summerframework.model.SummerService;
import org.summerframework.model.SummerServiceBean;

import javax.validation.constraints.NotNull;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.wise.model.content.ContentErrMsgs.Err_100100110004;

/**
 * @author yubo
 */
@Slf4j
@Service
@SummerService
public class CheckVerificationCodeService implements SummerServiceBean<CheckVerificationCode> {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Value("${verificationCode.checkTimes}")
    private Integer checkTimes;

    @Override
    public void sum(CheckVerificationCode summer) {
        String key = Consts.REDIS_VERIFY_KEY_KEY + summer.getUseType() + summer.getVerifyKey();
        String code = GetCodeFromCache.s(key);

        if (StringUtils.isBlank(code)) {
            throw new LogicException(this.getClass(), Err_100100110004);
        }

        boolean result;
        if (StringUtils.isNotBlank(summer.getMobile())) {
            result = checkVerificationCodeWithTimes(summer, key, code);
        } else {
            result = Objects.equals(summer.getCode(), code);
            SetCode2Cache.s(key, "");
        }

        CheckCodeResult ret = new CheckCodeResult();
        ret.setResult(result);
        summer.setSummerResult(ret);
    }

    private boolean checkVerificationCodeWithTimes(CheckVerificationCode summer, String key, String code) {
        boolean result;
        Integer times = 1;
        String[] split = StringUtils.split(code, "_");
        if (split.length > 1) {
            String checkCode = split[0];
            times = Integer.valueOf(split[1]);
            Integer nowTimes = times + 1;
            if (nowTimes >= checkTimes) {
                SetCode2Cache.s(key, "");
                result = false;
            } else {
                result = Objects.equals(summer.getCode() + summer.getMobile(), checkCode);
                if (!result) {
                    setRedisValueNoRefresh(key, checkCode + "_" + nowTimes);
                }
            }

        } else {
            result = Objects.equals(summer.getCode() + summer.getMobile(), code);
            if (!result) {
                setRedisValueNoRefresh(key, code + "_" + times);
            }
        }

        if (result) {
            SetCode2Cache.s(key, "");
        }
        return result;
    }

    private void setRedisValueNoRefresh(@NotNull String key, @NotNull String value) {
        Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
        expire = expire == null ? 0 : expire;
        redisTemplate.opsForValue().set(key, value, expire, TimeUnit.SECONDS);
        log.info("verify code redis key:{} value:{} expire:{}", key, value, expire);
    }
}
